package com.wizinno.android.urineflow.serialport;

import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import com.aill.androidserialport.ByteUtil;
import com.hoho.android.usbserial.driver.UsbSerialDriver;
import com.hoho.android.usbserial.driver.UsbSerialPort;
import com.hoho.android.usbserial.driver.UsbSerialProber;
import com.wizinno.android.urineflow.activity.MainActivity;
import com.wizinno.android.urineflow.constant.CommonConstant;
import com.wizinno.android.urineflow.constant.CommonControl;
import com.wizinno.android.urineflow.constant.MessageInfo;
import com.wizinno.android.urineflow.data.ErrorCodeEnum;
import com.wizinno.android.urineflow.receiver.USBPlugReceiver;
import com.wizinno.android.urineflow.util.LogUtils;
import com.wizinno.android.urineflow.util.ToastUtil;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * @author LiuMei
 * @date 2020-11-23.
 */
public class UsbHelper {

    private UsbManager usbManager;
    private UsbDevice usbDevice;
    private UsbInterface usbInterface;
    private UsbDeviceConnection usbDeviceConnection;

    private UsbSerialPort serialPort;
    private List<UsbSerialDriver> drivers;

    protected final Object mReadBufferLock = new Object();
    protected final Object mWriteBufferLock = new Object();

    private Context context;

    private final static String ACTION_USB_PERMISSION = "ACTION_USB_PERMISSION";

    //约定的接收数据长度
    public static int dataLength = 8;

    static int receiveLength = 16;
    int sendLength = 8;

    static byte[] receiveBytes = new byte[receiveLength];
    byte[] sendBytes = new byte[sendLength];
    Handler handler;
    MainActivity mainActivity;

    private static byte[] wholeData;
    private static int wholeDataSize;

    public static void initReceiveData() {
        wholeData = new byte[dataLength];
        wholeDataSize = 0;
        receiveBytes = new byte[receiveLength];
    }

    public UsbHelper(Context context, Handler mainHandler) {
        CommonConstant.usbInitLock.lock();
        if (CommonControl.INSTANCE.isUsbIn && !CommonControl.INSTANCE.isUsbInit) {
            usbInit(context, mainHandler);
        }
        CommonConstant.usbInitLock.unlock();
    }

    private void usbInit(Context thisContext, Handler mainHandler) {
        mainActivity = (MainActivity) thisContext;
        context = thisContext;
        handler = mainHandler;

        IntentFilter filter = new IntentFilter();
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        context.registerReceiver(new USBPlugReceiver(), filter);

        usbManager = (UsbManager) context.getSystemService(Context.USB_SERVICE);
        drivers = UsbSerialProber.getDefaultProber().findAllDrivers(usbManager);
        if (drivers.size() <= 0) {
            CommonControl.INSTANCE.isUsbIn = false;
            LogUtils.e(ErrorCodeEnum.NO_USB_DEVICE.getDesc());
            Message msg = new Message();
            Bundle data = new Bundle();
            msg.what = MessageInfo.WHAT_ERROR;
            data.putInt(MessageInfo.KEY_ERROR_CODE, ErrorCodeEnum.NO_USB_DEVICE.getCode());
            msg.setData(data);
            handler.sendMessage(msg);
            return;
        } else {
            CommonControl.INSTANCE.isUsbIn = true;
            usbDevice = drivers.get(0).getDevice();
            if (usbManager.hasPermission(usbDevice)) {
                initUsb(usbDevice);
            } else {
                LogUtils.e("没有权限");
                //申请USB权限
                applyUsbPermission();
            }
        }
    }

    private void applyUsbPermission() {
        UsbPermissionActionReceiver mUsbPermissionActionReceiver = new UsbPermissionActionReceiver();
        Intent intent = new Intent(ACTION_USB_PERMISSION);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);
        usbManager.requestPermission(usbDevice, pendingIntent);
        IntentFilter intentFilter = new IntentFilter(ACTION_USB_PERMISSION);
        context.registerReceiver(mUsbPermissionActionReceiver, intentFilter);
    }

    private void usbReceiveData() {
        ReceiveThread receiveThread = new ReceiveThread();
        new Thread(receiveThread).start();
    }

    class ReceiveThread implements Runnable {
        @Override
        public void run() {
            synchronized (mReadBufferLock) {
                while (!Thread.currentThread().isInterrupted() && serialPort != null) {
                    try {
                        Thread.sleep(100);
                        int read = serialPort.read(receiveBytes, 100);
                        int total = wholeDataSize + read;
                        if (total > 0 && total < dataLength) {
                            //不满约定的接收字节数
                            for (int i = 0; i < read; i++) {
                                wholeData[wholeDataSize + i] = receiveBytes[i];
                            }
                            wholeDataSize = total;
                        } else if (total >= dataLength) {
                            //补到上一个包里的字节
                            int preSize = dataLength - wholeDataSize;
                            for (int i = 0; i < preSize; i++) {
                                wholeData[wholeDataSize + i] = receiveBytes[i];
                            }
                            LogUtils.d("拼接后：" + ByteUtil.hexBytesToString(wholeData));
                            //把完整的数据发送出去处理
                            byte[] receive = wholeData;
                            Message msg = new Message();
                            Bundle data = new Bundle();
                            msg.what = MessageInfo.WHAT_USB_DATA;
                            data.putByteArray(MessageInfo.KEY_USB_DATA, receive);
                            msg.setData(data);
                            handler.sendMessage(msg);
                            initReceiveData();
                        }
                    } catch (IOException e) {
                        LogUtils.e("USB读取错误");
                        //中断线程
                        Thread.currentThread().interrupt();
                        e.printStackTrace();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public void usbSendData(byte[] send) {
        synchronized (mWriteBufferLock) {
            sendBytes = new byte[sendLength];
            for (int i = 0; i < send.length; i++) {
                sendBytes[i] = send[i];
            }
            SendThread sendThread = new SendThread();
            new Thread(sendThread).start();
        }
    }

    class SendThread implements Runnable {
        @Override
        public void run() {
            try {
                if (serialPort != null) {
                    serialPort.write(sendBytes, 100);
                    LogUtils.d("发送数据：" + ByteUtil.hexBytesToString(sendBytes));
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    private void initUsb(UsbDevice device) {
        List<UsbSerialPort> result = new ArrayList<>();
        for (final UsbSerialDriver driver : drivers) {
            final List<UsbSerialPort> ports = driver.getPorts();
            result.addAll(ports);
        }
        usbDeviceConnection = usbManager.openDevice(device);
        try {
            serialPort = result.get(0);
            if (!serialPort.isOpen()) {
                serialPort.open(usbDeviceConnection);
            }
            serialPort.setParameters(115200, 8, UsbSerialPort.STOPBITS_1, UsbSerialPort.PARITY_NONE);
        } catch (IOException e) {
            e.printStackTrace();
        }
        usbInterface = device.getInterface(0);
        if (usbInterface == null) {
            LogUtils.e("USB初始化失败");
            CommonControl.INSTANCE.isUsbInit = false;
            return;
        } else {
            LogUtils.d("USB初始化成功");
            CommonControl.INSTANCE.isUsbInit = true;
            initReceiveData();
            usbReceiveData();
            usbInitSend();
        }
    }

    private void usbInitSend() {
        usbSendData(SerialProtocol.COLLECT_END);
        CommonControl.INSTANCE.isWight = false;
        usbSendData(SerialProtocol.A1_VERSION);
        try {
            Thread.sleep(200);
            usbSendData(SerialProtocol.A2_VERSION);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private class UsbPermissionActionReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if (ACTION_USB_PERMISSION.equals(action)) {
                synchronized (this) {
                    UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        if (null != usbDevice) {
                            initUsb(usbDevice);
                        }
                    } else {
                        ToastUtil.showLong(context, "USB权限申请失败,请重新授权");
                        applyUsbPermission();
                    }
                }
            }
        }
    }
}
